package com.triones.api.service.third;

import cn.hutool.core.convert.Convert;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.config.LeptageConfig;
import com.ruoyi.common.constant.LeptageApiPathConstants;
import com.ruoyi.common.utils.LeptageApiSignUtils;
import com.ruoyi.common.utils.PhpApiSignUtils;
import com.triones.api.entity.CardLinkBodyBO;
import com.triones.api.entity.LptBeneficiaryRequestBodyBO;
import com.triones.api.entity.WithdrawCryptoRequstBodyBO;
import com.triones.api.entity.bo.*;
import com.triones.api.entity.param.BalanceRequestParams;
import com.triones.api.entity.param.TotalBalanceRequestParams;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * lpt 接口（调用第三方）业务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LeptageServiceImpl implements LeptageService {

    private final LeptageConfig leptageConfig;

    private final OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(15, TimeUnit.SECONDS)
        .build();

    @Override
    public Map wallet(CardLinkBodyBO bo) {
        return (Map) sendPost(LeptageApiPathConstants.wallet, bo);
    }

    @Override
    public List<Map> balance(BalanceRequestParams params,String accountId) {
        return (List<Map>) sendGet(LeptageApiPathConstants.balance, params,accountId);
    }

    @Override
    public Map withdraw(WithdrawRequestBodyBO bo) {
        return (Map) sendPost(LeptageApiPathConstants.withdraw, bo);
    }

    @Override
    public Map crypto(CryptoRequestBodyBO bo, String accountId) {
        return (Map) sendPost(LeptageApiPathConstants.crypto, bo,accountId);
    }

    @Override
    public boolean mockDepositCrypto(CryptoWalletRequestBodyBO bo) {
        return (boolean) sendPost(LeptageApiPathConstants.mock, bo);
    }

    @Override
    public List<Map> mockBalance(BalanceRequestParams params,String accountId) {
        return (List<Map>) sendGet(LeptageApiPathConstants.mockBalance, params,accountId);
    }

    @Override
    public boolean delAddress(String beneId) {
        return (boolean) sendDelete(LeptageApiPathConstants.delAddress, beneId);
    }

    @Override
    public Boolean mockWithdrawCrypto(WithdrawCryptoRequstBodyBO bo) {
        return (boolean) sendPost(LeptageApiPathConstants.withdrawCrypto, bo);
    }

    @Override
    public Map transfer(TransferRequestBodyBO bo, String accountId, String direction) {
        return (Map) sendPost(LeptageApiPathConstants.transfer, bo,accountId,direction);
    }

    @Override
    public Map lptQuote(LptQuoteRequestBodyBO bo) {
        return (Map) sendGet(LeptageApiPathConstants.lptQuote, bo,null);
    }

    @Override
    public List<Map> totalBalance(TotalBalanceRequestParams params) {
        return (List<Map>) sendGet(LeptageApiPathConstants.totalBalance, params,null);
    }

    @Override
    public Map lptExchange(LptExchangeRequestBodyBO bo) {
        return (Map) sendPost(LeptageApiPathConstants.lptExchange, bo,null);
    }

    @Override
    public Map lptWithdraw(LptWithdrawRequestBodyBO bo) {
        return (Map) sendPost(LeptageApiPathConstants.lptWithdraw, bo,null);
    }

    @Override
    public List<Map> lptBeneficiary(LptBeneficiaryRequestBodyBO bo) {
        return (List<Map>) sendPost(LeptageApiPathConstants.lptBeneficiary, bo,null);
    }

    public Object sendGet(String apiLink,Object obj,String pathParam) {
        String time = Convert.toStr(Instant.now().toEpochMilli());
        String sortAndEncodeParams = LeptageApiSignUtils.sortAndEncodeParams(obj);
        OkHttpClient client = new OkHttpClient().newBuilder()
            .build();
        String url = "";
        if (pathParam == null) {
            url = leptageConfig.getUrl() + apiLink;
        } else {
            url = leptageConfig.getUrl() + apiLink + pathParam;
        }
        if (sortAndEncodeParams != null && !sortAndEncodeParams.equals("")) {
            url = url + "?" + sortAndEncodeParams;
        }
        Request request = new Request.Builder()
            .url(url)
            .header("X-API-KEY",leptageConfig.getAppid())
            .header("X-API-SIGNATURE",LeptageApiSignUtils.signData(leptageConfig.getAppsecret(),sortAndEncodeParams,"GET",apiLink,time,pathParam))
            .header("X-API-NONCE",time)
            .get()
            .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                ObjectMapper objectMapper = new ObjectMapper();
                String responseBody = response.body().string();
                log.info("成功 - 响应参数 : {}", responseBody);
                Map<String, Object> responseMap = objectMapper.readValue(responseBody, Map.class);
                if (responseMap.get("code").equals("0000")) {
                    System.out.println("responseMap.get(data) = " + responseMap.get("data"));
                    return responseMap.get("data");
                }
            } else {
                log.error("Request failed: {}", response.code());
                String responseBody = response.body().string();
                log.error("失败 - 响应参数 ：{}", responseBody);
                System.out.println("失败 - 响应参数 ：" + responseBody);
                throw new SecurityException("");
            }
        } catch (IOException e) {
            log.error("IOException occurred: ", e);
            throw new SecurityException("");
        }
        throw new SecurityException("repeated requests");
    }


    public Object sendDelete(String apiLink,String pathParam) {
        String time = Convert.toStr(Instant.now().toEpochMilli());
        OkHttpClient client = new OkHttpClient().newBuilder()
            .build();
        String url = "";
        if (pathParam == null) {
            url = leptageConfig.getUrl() + apiLink;
        } else {
            url = leptageConfig.getUrl() + apiLink + pathParam;
        }
        Request request = new Request.Builder()
            .url(url)
            .header("X-API-KEY",leptageConfig.getAppid())
            .header("X-API-SIGNATURE",LeptageApiSignUtils.signData(leptageConfig.getAppsecret(),null,"DELETE",apiLink,time,pathParam))
            .header("X-API-NONCE",time)
            .delete()
            .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                ObjectMapper objectMapper = new ObjectMapper();
                String responseBody = response.body().string();
                log.info("成功 - 响应参数 : {}", responseBody);
                Map<String, Object> responseMap = objectMapper.readValue(responseBody, Map.class);
                if (responseMap.get("code").equals("0000")) {
                    System.out.println("responseMap.get(data) = " + responseMap.get("data"));
                    return responseMap.get("data");
                }
            } else {
                log.error("Request failed: {}", response.code());
                String responseBody = response.body().string();
                log.error("失败 - 响应参数 ：{}", responseBody);
                System.out.println("失败 - 响应参数 ：" + responseBody);
                throw new SecurityException("");
            }
        } catch (IOException e) {
            log.error("IOException occurred: ", e);
            throw new SecurityException("");
        }
        throw new SecurityException("repeated requests");
    }


    /**
     * 发送post请求
     * @param apiLink
     * @param obj
     * @return
     */
    public Object sendPost(String apiLink,Object obj) {
        return this.sendPost(apiLink, obj,null);
    }

    /**
     * 发送post请求
     * @param obj
     * @return
     */
    public Object sendPost(String apiLink,Object obj,String pathParam1,String pathParam2) {
        String pathParam = pathParam1 + "/" + pathParam2;
        return this.sendPost(apiLink, obj,pathParam);
    }

    public Object sendPost(String apiLink,Object obj,String pathParam) {
        String time = Convert.toStr(Instant.now().toEpochMilli());
        String objectToJson = PhpApiSignUtils.convertObjectToJson(obj);
        String contentType = "application/json";
        MediaType mediaType = MediaType.parse(contentType);
        //根据实际需要设置请求体内容
        RequestBody body = RequestBody.create(mediaType,objectToJson);

        String url = leptageConfig.getUrl() + apiLink;
        if (pathParam != null && !pathParam.equals("")) {
            url = url + pathParam;
        }
        Request request = new Request.Builder()
            .url(url)
            .post(body)
            .header("content-type", contentType)
            .header("X-API-KEY",leptageConfig.getAppid())
            .header("X-API-SIGNATURE",LeptageApiSignUtils.signData(leptageConfig.getAppsecret(),objectToJson,"POST",apiLink,time,pathParam))
            .header("X-API-NONCE",time)
            .build();
        System.out.println("request = " + request);
        try (Response response = client.newCall(request).execute()) {
            log.info("响应 response = " + response);
            ObjectMapper objectMapper = new ObjectMapper();
            String responseBody = response.body().string();
            Map<String, Object> responseMap = objectMapper.readValue(responseBody, Map.class);
            log.info("请求时间: " + responseMap);
            if (response.isSuccessful()) {
                log.info("成功 - 响应参数 : {}", responseBody);
                if (responseMap.get("code").equals("0000")) {
                    System.out.println("responseMap.get(data) = " + responseMap.get("data"));
                    return responseMap.get("data");
                }
            } else {
                log.error("Request failed: {}", response.code());
                log.error("失败 - 响应参数 ：{}", responseBody);
                System.out.println("失败 - 响应参数 ：" + responseBody);
                throw new SecurityException(Convert.toStr(responseMap.get("msg")));
            }
        } catch (IOException e) {
            log.error("IOException occurred: ", e);
            log.info("IOException occurred: ", e);
            throw new SecurityException("请求出错");
        }
        throw new SecurityException("repeated requests");
    }
}
